home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C++ / Applications / Nuntius 1.2 / src / Nuntius / UThreadApple.cp < prev    next >
Encoding:
Text File  |  1994-03-16  |  5.9 KB  |  246 lines  |  [TEXT/MPS ]

  1. // Copyright © 1993 Peter Speck (speck@dat.ruc.dk).  All rights reserved.
  2. // UThreadApple.cp
  3.  
  4. #include "UThreadApple.h"
  5. #include "UFatalError.h"
  6.  
  7. #include <RsrcGlobals.h>
  8.  
  9. #include <GestaltEqu.h>
  10.  
  11. #pragma segment MyThread
  12.  
  13. #define qDebugThreadCommands qDebug & 0
  14.  
  15. #define qDebugSchedule qDebug & 0
  16.  
  17. const long kInitialStackSize = 24 * 1024;
  18.  
  19. //==============================================================================
  20.  
  21. TThreadApple::TThreadApple()
  22. {
  23. }
  24.  
  25. pascal void TThreadApple::Initialize()
  26. {
  27.     inherited::Initialize();
  28.     fThreadID = kNoThreadID;
  29. }
  30.  
  31. void TThreadApple::IThreadApple(Boolean isMainThread, const char *debugDoingWhat)
  32. {
  33.     inherited::IThread(isMainThread, debugDoingWhat);
  34. }
  35.  
  36. pascal void TThreadApple::Free()
  37. {
  38.     if (fIsMainThread == false && fThreadID != kNoThreadID)
  39.     {
  40.         OSErr err = DisposeThread(fThreadID, 0, false);
  41.         if (err != noErr)
  42.         {
  43.             sprintf(gPanicBuffer, "Got OSErr %ld from DisposeThread", long(err));
  44.             PanicExitToShell(gPanicBuffer);
  45.         }
  46.     }
  47.     inherited::Free();
  48. }
  49.  
  50. void TThreadApple::Die()
  51. {
  52. #if qDebugSchedule
  53.     fprintf(stderr, "ThreadDie, id = %ld, %s\n", fThreadID, fDebugDoingWhat);
  54. #endif
  55.     ThreadID id = fThreadID; // we're going to shoot ourself!
  56.     fThreadID = kNoThreadID;
  57.     inherited::Die();
  58. #if qDebugSchedule
  59.     fprintf(stderr, "ThreadDie, Goes disposing of: id = %ld\n", id);
  60. #endif
  61.     OSErr err = DisposeThread(id, 0, false);
  62.     sprintf(gPanicBuffer, "In TThreadApple::Die, got past end of world with OSErr %ld", long(err));
  63.     PanicExitToShell(gPanicBuffer);
  64. }
  65.  
  66. //-----------------------------------------------------------------------------
  67. void TThreadApple::CallSaveState()
  68. {
  69.     SaveState();
  70. }
  71.  
  72. void TThreadApple::CallRestoreState()
  73. {
  74.     RestoreState();
  75. }
  76.  
  77. pascal void ThreadAppleSwitchIn(ThreadID threadID, void *param)
  78. {
  79.     long oldA5 = SetCurrentA5();
  80.     TThreadApple *thread = (TThreadApple*)param;
  81.     if (VerboseIsObject(thread))
  82.     {
  83.         if (qDebugSchedule)
  84.             fprintf(stderr, "SwitchIn,  id = %ld, param = $%lx, %s\n", threadID, param, thread->PeekShortDescription());
  85.         thread->CallRestoreState();
  86.     }
  87.     else
  88.         if (qDebug)
  89.             DebugStr("\pUps, its not an object!");
  90.     SetA5(oldA5);
  91. }
  92.  
  93. pascal void ThreadAppleSwitchOut(ThreadID threadID, void *param)
  94. {
  95.     long oldA5 = SetCurrentA5();
  96.     TThreadApple *thread = (TThreadApple*)param;
  97.     if (VerboseIsObject(thread))
  98.     {
  99.         if (qDebugSchedule)
  100.             fprintf(stderr, "SwitchOut, id = %ld, param = $%lx, %s\n", threadID, param, thread->PeekShortDescription());
  101.         thread->CallSaveState();
  102.     }
  103.     else
  104.         if (qDebug)
  105.             DebugStr("\pUps, its not an object!");
  106.     SetA5(oldA5);
  107. }
  108.  
  109. void TThreadApple::InstallSwitchers()
  110. {
  111.     OSErr err = SetThreadSwitcher(fThreadID, ThreadAppleSwitchIn, this, true);
  112. #if qDebug
  113.     if (err)
  114.         fprintf(stderr, "OSErr from SetThreadSwitcher.In = %ld\n", long(err));
  115. #endif
  116.     err = SetThreadSwitcher(fThreadID, ThreadAppleSwitchOut, this, false);
  117. #if qDebug
  118.     if (err)
  119.         fprintf(stderr, "OSErr from SetThreadSwitcher.Out = %ld\n", long(err));
  120. #endif
  121. }
  122. //==============================================================================
  123.  
  124. void TThreadApple::StartThread(ThreadID threadID)
  125. {
  126.     if (fThreadID != kNoThreadID)
  127.         PanicExitToShell("Has already a threadID");
  128.     fThreadID = threadID;
  129.     InstallSwitchers();
  130.     gAllThreads->InsertLast(this);
  131.     fIsStarted = true;
  132. #if qDebugSchedule
  133.     fprintf(stderr, "Starts AppleThread id %ld at $%lx (%s)\n", threadID, this, fDebugDoingWhat);
  134. #endif
  135.     FailOSErr(SetThreadState(fThreadID, kReadyThreadState, fThreadID));
  136. }
  137.  
  138. void TThreadApple::SwapThread()
  139. {
  140.     TThreadApple *nextThread = (TThreadApple*)MySchedule();
  141.     if (nextThread == this)
  142.     {
  143. #if qDebug
  144.         fprintf(stderr, "Yeild (MySchedule) to current thread\n");
  145. #endif
  146.         return;
  147.     }
  148.     OSErr err = YieldToThread(nextThread->fThreadID);
  149. #if qDebug
  150.     if (err != noErr)
  151.         fprintf(stderr, "Got error from YieldToThread: %ld\n", long(err));
  152. #endif
  153. }
  154.  
  155. void TThreadApple::DumpDebugDescription()
  156. {
  157.     inherited::DumpDebugDescription();
  158.     unsigned long stackFree;
  159.     FailOSErr(ThreadCurrentStackSpace(fThreadID, &stackFree));
  160.     fprintf(stderr, "       stack-free = %ld\n", stackFree);
  161. }
  162. //===============================================================================
  163. pascal void *ThreadAppleEntry(void *param)
  164. {
  165.     TCommand *cmd = (TCommand*)param;
  166. #if qDebug
  167.     if (!VerboseIsObject(cmd))
  168.         ProgramBreak("param is bad!");
  169. #endif
  170.     ThreadExecuteCommand(cmd);
  171.     return 0;
  172. }
  173.  
  174. TThread *ExecuteInNewThreadApple(TCommand *command, const char *debugDoingWhat)
  175. {
  176. #if qDebugSchedule
  177.     fprintf(stderr, "ExecuteInNewThreadApple, cmd = $%lx, doing: %s\n", command, debugDoingWhat);
  178. #endif
  179.     TThreadApple *thread = nil;
  180.     VOLATILE(thread);
  181.     //
  182.     ThreadID threadID = kNoThreadID;
  183.     VOLATILE(threadID);
  184.     //
  185.     FailInfo fi;
  186.     if (fi.Try())
  187.     {
  188.         TThreadApple *ta = new TThreadApple();
  189.         ta->IThreadApple(false, debugDoingWhat);
  190.         thread = ta;
  191.         //
  192.         ThreadID threadID;
  193.         FailOSErr(NewThread(kCooperativeThread, ThreadAppleEntry, command,
  194.                 kInitialStackSize, kNewSuspend|kCreateIfNeeded|kFPUNotNeeded, nil, &threadID));
  195.         //
  196.         FailSpaceIsLow();
  197.         thread->StartThread(threadID);
  198.         //
  199.         fi.Success();
  200.         return thread;
  201.     }
  202.     else // fail
  203.     {
  204.         FreeIfObject(command); command = nil;
  205.         FreeIfObject(thread); thread = nil;
  206.         if (threadID != kNoThreadID)
  207.         {
  208.             OSErr err = DisposeThread(kNoThreadID, 0, false);
  209.             if (err != noErr)
  210.             {
  211.                 sprintf(gPanicBuffer, "Got OSErr %ld from DisposeThread", long(err));
  212.                 PanicExitToShell(gPanicBuffer);
  213.             }
  214.         }
  215.         fi.ReSignal();
  216.     }
  217. }
  218. //===========================================================================
  219. Boolean HasThreadApple()
  220. {
  221. #if qDebug
  222.     return false; // want to test my own
  223. #else
  224.     long resp;
  225.     if (Gestalt(gestaltThreadMgrAttr, resp) != noErr)
  226.         return false;
  227.     // not 100% compatible with MacPlus:
  228.     if (Gestalt(gestaltMachineType, resp) != noErr)
  229.         return false;
  230.     if (resp == gestaltMacPlus)
  231.         return false;
  232.     return true;
  233. #endif
  234. }
  235.  
  236. TThread *CreateMainThreadApple()
  237. {
  238.     TThreadApple *thread = new TThreadApple();
  239.     thread->IThreadApple(true, "main thread");
  240.     ThreadID threadID;
  241.     if (GetCurrentThread(&threadID) != noErr)
  242.         PanicExitToShell("GetCurrentThread won't play");
  243.     thread->StartThread(threadID);
  244.     return thread;
  245. }
  246.